package com.bb.flow.service;

import com.bb.flow.api.FlowEndCallback;
import com.bb.flow.api.FlowStartCallback;
import com.bb.flow.api.NodeExecuteStateCallback;
import com.bb.flow.api.exception.ParseException;
import com.bb.flow.config.AbstractConfigNode;
import com.bb.flow.config.FlowInfo;
import com.bb.flow.parser.NodeParser;
import com.bb.flow.service.exception.FlowTemplateNameAlreadyExistException;
import com.bb.flow.service.exception.FlowTemplateNameNullException;
import com.bb.flow.service.exception.FlowTemplateNotFoundException;
import com.bb.flow.service.exception.FlowTextInfoNullException;

import java.util.List;

/**
 * @author bigbeard
 * 流程驱动
 */
public interface FlowDriver {

    /**
     * 启动流程
     *
     * @param flowTemplateName 流程模板名称
     * @param flowInstanceName 流程实例名称
     * @param context          流程上下文
     * @throws FlowTemplateNotFoundException 找不到模板
     */
    void startFlow(String flowTemplateName, String flowInstanceName, Object context) throws
            FlowTemplateNotFoundException, FlowTemplateNameNullException, ParseException;

    /**
     * 启动流程
     *
     * @param flowTemplateName 流程模版名称
     * @param flowInstanceName 流程实例名称
     * @param parent           父流程信息
     * @param context          流程上下文参数(驱动不会使用该参数,主要是用业务节点之间使用)
     * @throws FlowTemplateNotFoundException 流程不存在
     */
    void startFlow(String flowTemplateName, String flowInstanceName, FlowInfo parent, Object context) throws
            FlowTemplateNotFoundException, FlowTemplateNameNullException, ParseException;

    /**
     * 从指定节点开始启动
     *
     * @param templateName 流程模板名称
     * @param instanceName 流程实例名称
     * @param nodeKey      启动节点
     * @param parent       上级流程
     * @param context      流程上下文参数(驱动不会使用该参数,主要是用业务节点之间使用)
     * @throws FlowTemplateNotFoundException 流程不存在
     */
    void startFlow(
            String templateName, String instanceName, String nodeKey, FlowInfo parent, Object context)
            throws FlowTemplateNotFoundException, FlowTemplateNameNullException, ParseException;

    /**
     * 停止正在执行的流程
     *
     * @param flowInstanceName 流程实例名称
     */
    void stopFlow(String flowInstanceName);

    /**
     * 判断流程是否符合启动条件
     *
     * @param flowTemplateName 流程模版名称
     * @param context          上下文参数
     * @return true:符合条件,false:不符合条件
     * @throws FlowTemplateNotFoundException 流程不存在
     */
    boolean confirmCanFlowStart(String flowTemplateName, Object context)
            throws FlowTemplateNotFoundException,  FlowTemplateNameNullException, ParseException;

    /**
     * 添加流程模板
     *
     * @param flowInfo 需要添加的流程模板对象
     * @throws FlowTemplateNameAlreadyExistException 流程模版名称已经存在
     * @throws FlowTextInfoNullException             流程空指针异常
     */
    void addFlowTemplate(FlowInfo flowInfo) throws FlowTemplateNameAlreadyExistException, FlowTextInfoNullException;

    /**
     * 添加流程
     *
     * @param textFlow 流程文本配置内容
     * @throws FlowTemplateNameAlreadyExistException 流程模版名称已经存在
     * @throws FlowTextInfoNullException             模版空指针异常
     */
    void addFlowTemplate(String textFlow) throws FlowTemplateNameAlreadyExistException, FlowTextInfoNullException, FlowTemplateNameNullException, ParseException;

    /**
     * 获取流程实例
     *
     * @param flowTemplateName 流程模板名称
     * @return 流程实例
     * @throws FlowTemplateNotFoundException 流程模板未找到
     */
    FlowInfo createFlowInstance(String flowTemplateName) throws FlowTemplateNotFoundException, FlowTemplateNameNullException, ParseException;

    /**
     * 移除一个流程模板
     *
     * @param flowTemplateName 流程模板名称
     */
    void removeFlowTemplate(String flowTemplateName);


    /**
     * 注册流程启动回调
     *
     * @param flowStartCallback 回调通知
     */
    void registerFlowStartCallback(FlowStartCallback flowStartCallback);

    /**
     * 取消注册流程启动回调
     *
     * @param flowStartCallback 回调通知
     */
    void unregisterFlowStartCallback(FlowStartCallback flowStartCallback);

    /**
     * 注册流程执行状态监听
     *
     * @param callback 监听器
     */
    void registerNodeExecuteStateCallback(NodeExecuteStateCallback callback);

    /**
     * 取消注册流程执行状态监听
     *
     * @param callback 监听器
     */
    void unregisterNodeExecuteStateCallback(NodeExecuteStateCallback callback);

    /**
     * 注册流程执行结束监听
     *
     * @param callback 监听器
     */
    void registerFlowEndCallback(FlowEndCallback callback);

    /**
     * 取消注册流程执行结束监听
     *
     * @param callback 监听器
     */
    void unregisterFlowEndCallback(FlowEndCallback callback);

    /**
     * 获取一个正在执行的流程实例
     *
     * @param instanceName 流程实例名称
     * @return 流程实例信息
     */
    FlowInfo getFlowInstance(String instanceName);

    /**
     * 获取正在运行的所有的流程实例
     *
     * @return 流程实例信息
     */
    List<FlowInfo> getFlowInstance();

    /**
     * 将节点加入到执行缓存,准备执行
     *
     * @param node     被执行的节点
     * @param flowInfo 节点所在流程
     */
    void prepareExecute(AbstractConfigNode node, FlowInfo flowInfo);

    /**
     * 执行流程节点
     *
     * @param flowInfo 流程
     * @param node     节点
     */
    void executeNode(AbstractConfigNode node, FlowInfo flowInfo);

    /**
     * 设置流程文件解析器
     *
     * @param parser 解析器
     */
    void setParser(NodeParser parser);

    /***
     * 获取所有流程模板名称
     * @return 流程模板名称
     */
    List<String> getAllTemplateNames();
}
